/*--------------------------------------------------------------------------------
* Copyright (c) 2022,西北农林科技大学信息学院计算机科学系
* All rights reserved.
*
* 文件名称：main.c
* 文件标识：见配置管理计划书
* 摘要：颠倒句子中单词，用两次逆序字符串方式实现。
*       首先遍历字符串，根据分隔符定位每个单词在原字符串中的起始地址和结束地址。
*       然后对每个单词进行逆序操作。
*       最后再对整个句子字符串进行逆序操作。
*
* 当前版本：1.0
* 作者：耿楠
* 完成日期：2022年11月26日
*
* 取代版本：无
* 原作者：耿楠
* 完成日期：
------------------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define N 10

/* 函数原型 */
void revString(char*, char*);
char *removeDupSpaces(char*, const char*);
char* revSentenceWords(char *, const char*);
/* 判断是否为一个句子 */
int isSentence(const char *, const char *);

/* 错误响应 */
static void errormsg(const char *);

int main()
{
    /* 句子 */
    /* char s[] = "you can cage a swallow can't you?"; */
    char s[] = "   you can \n  cage a \tswallow  \ncan't you?   ";

    /* 原句子单词分隔符 */
    char delim[] = " \t\n\r";
    /* 句子终止符 */
    char term[] = ".?!";
    /* 结果句子单词分隔符 */
    char hyphen[] = " ";

    removeDupSpaces(s, delim);
    if(!isSentence(s, term))
    {
        errormsg("Sentence needs a terminating character. (./?/!)");
    }

    revSentenceWords(s, hyphen);
    puts(s);

    return 0;
}

/* 错误响应 */
static void errormsg(const char *message)
{
    printf("%s\n", message);
    exit(EXIT_FAILURE);
}

int isSentence(const char *s, const char *term)
{
    size_t len = 0;

    len = strlen(s);

    /* 判断最后一个字符是不是句子终止字符 */
    if(!strchr(term, s[len - 1]))
    {
        return 0;
    }

    return 1;
}

/*---------------------------------------------------------
// 名称：void revString(char* p, char* q)
// 功能：原地逆序，对指针p和q之间的字符进行逆序操作。
// 参数：
//       [char* p] --- 待逆序字符串起始指针
//       [char* q] --- 待逆序字符串结束指针
// 返回：[void] --- 无
// 作者：耿楠
// 日期：2022年11月26日
--------------------------------------------------------*/
void revString(char* p, char* q)
{
    char ch;

    while(p < q)
    {
        ch = *p;
        *p++ = *q;
        *q-- = ch;
    }
}

/*---------------------------------------------------------
// 名称：char *removeDupSpaces(char *s, const char *delim)
// 功能：将字符串中指定的分隔字符集中的字符压缩并替换为1个空格。
// 参数：
//       [char* s] ------------- 待处理的字符串指针
//       [const char* delim] --- 分隔字符集指针
// 返回：[char *] --- 结果字符串
// 作者：耿楠
// 日期：2022年11月26日
--------------------------------------------------------*/
char *removeDupSpaces(char *s, const char *delim)
{
    size_t len;
    char *p = s;
    char *str, *q;

    /* 申请一个对原串等长的字符串 */
    len = strlen(s);
    str = (char*)malloc((len + 1) * sizeof(char));
    if(str == NULL)
    {
        errormsg("Not enough memory for temp string.");
    }
    q =  str;

    /* 删除前导空白 */
    while(strchr(delim, *p))
    {
        p++;
    }

    /* 删除尾部空白 */
    len = strlen(p);
    while(strchr(delim, p[len - 1]))
    {
        p[len - 1] = '\0';
        len--;
    }

    /* 复制前后修剪后的字符串 */
    strcpy(str, p);

    /* 压缩字符串中的分隔符为一个空格 */
    p = s;
    while(*q)
    {
        /* 连续的分隔符 */
        while(strchr(delim, *q) && strchr(delim, *(q + 1)))
        {
            q++;
        }

        /* 将分隔符替换为空格 */
        if(strchr(delim, *q))
        {
             *p++ = ' ';
             q++;
        }
        else
        {
            *p++ = *q++;
        }
    }

    /* 字符串终止字符 */
    *p = '\0';

    /* 释放空间 */
    free(str);

    return s;
}

/*---------------------------------------------------------
// 名称：char* revSentenceWords(char *s, const char *hyphen)
// 功能：将句子按单词逆序(单词必须以空格分隔)。
// 算法：先对每个单词逆序，再对整个字符串逆序，如：
//       This is a sentence
//       sihT si a ecnetnes
//       sentence a is This
// 参数：
//       [char* s] -------------- 待逆序的字符串的指针
//       [const char* hyphen] --- 结果单词分隔字符集指针
// 返回：[char*] --- 逆序后字符串的指针
// 作者：耿楠
// 日期：2022年11月26日
--------------------------------------------------------*/
char* revSentenceWords(char *s, const char *hyphen)
{
    char* p = s; /* 指向单词的首字符 */
    char* q = s; /* 指向空格或者 '\0' */
    size_t len = strlen(s);
    char terminator = s[len - 1];
    s[len - 1] = '\0';

    while(*q != '\0')
    {
        if (*q == ' ')
        {
            /* 单词逆序 */
            revString(p, q - 1);
            /* 处理下一个单词 */
            q++;
            p = q;
        }
        else
        {
            /* 继续查找单词分隔符 */
            q++;
        }
    }

    /* 对最后一个单词逆序 */
    revString(p, q - 1);

    /* 对整个句子逆序 */
    revString(s, q - 1);

    /* 添加句子终止符 */
    s[len - 1] = terminator;

    /* 如果传入了单词分隔符，则将空格替换为指定分隔符 */
    if(hyphen != NULL)
    {
        p = s;
        while(*p)
        {
            if(*p == ' ')
            {
                *p = hyphen[0];
            }
            p++;
        }
    }

    return s;
}
